package org.jeecg.modules.ws.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.ws.entity.WsBankDetail;
import org.jeecg.modules.ws.entity.WsBankInfo;
import org.jeecg.modules.ws.entity.WsBankForewarn;
import org.jeecg.modules.ws.entity.WsBankBlockTrade;
import org.jeecg.modules.ws.service.IWsBankDetailService;
import org.jeecg.modules.ws.service.IWsBankInfoService;
import org.jeecg.modules.ws.service.IWsBankForewarnService;
import org.jeecg.modules.ws.service.IWsBankBlockTradeService;
import org.jeecg.modules.ws.util.WyzlAccountDetailRequest;
import org.jeecg.modules.ws.util.WyzlAccountDetailResponse;
import org.jeecg.modules.ws.util.WyzlClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 银行账户明细查询定时任务
 */
@Slf4j
@Component
public class BankDetailJob {

    @Autowired
    private IWsBankInfoService wsBankInfoService;

    @Autowired
    private IWsBankDetailService wsBankDetailService;

    @Autowired
    private IWsBankForewarnService wsBankForewarnService;

    @Autowired
    private IWsBankBlockTradeService wsBankBlockTradeService;

    @Autowired
    private WyzlClient wyzlClient;

    /**
     * 检查并保存大额交易
     */
    private void checkAndSaveBlockTrade(WsBankInfo bankInfo, WyzlAccountDetailResponse.DetailInfo detail, BigDecimal txnAmount) {
        try {
            // 查询账户预警配置
            LambdaQueryWrapper<WsBankForewarn> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(WsBankForewarn::getBankNo, bankInfo.getBankNo())
                   .eq(WsBankForewarn::getDelFlag, "0");
            WsBankForewarn forewarn = wsBankForewarnService.getOne(wrapper);

            // 如果存在预警配置且交易金额超过大额交易阈值
            if (forewarn != null && forewarn.getBlockTrade() != null 
                && txnAmount.compareTo(forewarn.getBlockTrade()) >= 0) {
                
                // 检查是否已存在该笔大额交易记录
                LambdaQueryWrapper<WsBankBlockTrade> blockWrapper = new LambdaQueryWrapper<>();
                blockWrapper.eq(WsBankBlockTrade::getBankNo, bankInfo.getBankNo())
                           .eq(WsBankBlockTrade::getTxnTime, detail.getTranDate() + " " + detail.getTranTime())
                           .eq(WsBankBlockTrade::getTxnAmount, txnAmount);
                
                if (wsBankBlockTradeService.count(blockWrapper) == 0) {
                    // 创建大额交易记录
                    WsBankBlockTrade blockTrade = new WsBankBlockTrade();
                    blockTrade.setCompanyName(bankInfo.getDepartName());
                    blockTrade.setBankName(bankInfo.getBankName());
                    blockTrade.setBankNo(bankInfo.getBankNo());
                    blockTrade.setTxnAmount(txnAmount);
                    blockTrade.setIncOrExp("1".equals(detail.getFlag1()) ? "收入" : "支出");
                    
                    // 设置交易时间
                    SimpleDateFormat txnSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    blockTrade.setTxnTime(txnSdf.parse(detail.getTranDate() + " " + detail.getTranTime()));
                    
                    // 保存大额交易记录
                    wsBankBlockTradeService.save(blockTrade);
                    log.info("账户[{}]新增大额交易记录，金额：{}", bankInfo.getBankNo(), txnAmount);
                }
            }
        } catch (Exception e) {
            log.error("检查大额交易异常", e);
        }
    }

    /**
     * 每小时执行一次
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void queryAccountDetail() {
        log.info("开始执行银行账户明细查询定时任务");
        try {
            // 查询所有银行账户信息
            List<WsBankInfo> bankInfoList = wsBankInfoService.list();

            for (WsBankInfo bankInfo : bankInfoList) {
                try {
                    // 获取最近一次交易时间
                    Date lastTxnTime = getLastTxnTime(bankInfo.getBankNo());

                    // 设置查询时间范围
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                    Date now = new Date();
                    String endDate = sdf.format(now);
                    String startDate = lastTxnTime != null ? sdf.format(lastTxnTime) : sdf.format(new Date(now.getTime() - 30L * 24 * 60 * 60 * 1000));

                    int page = 1;
                    int pageSize = 100;
                    int maxPage = 1000; // 设置最大页数限制，防止死循环
                    boolean hasMore = true;

                    while (hasMore && page <= maxPage) {
                        log.info("账户[{}]开始查询第{}页明细", bankInfo.getBankNo(), page);
                        
                        // 构建账户明细查询请求
                        WyzlAccountDetailRequest request = new WyzlAccountDetailRequest();
                        WyzlAccountDetailRequest.TxInfo txInfo = new WyzlAccountDetailRequest.TxInfo();
                        txInfo.setAccNo1(bankInfo.getBankNo());
                        txInfo.setCurrCod("156"); // 人民币
                        txInfo.setStartDate(startDate);
                        txInfo.setEndDate(endDate);
                        txInfo.setPage(String.valueOf(page));
                        txInfo.setTotalRecord(String.valueOf(pageSize));
                        request.setTxInfo(txInfo);

                        // 发送请求
                        WyzlAccountDetailResponse response = wyzlClient.queryAccountDetail(request);

                        // 处理响应结果
                        if ("000000".equals(response.getReturnCode()) && response.getTxInfo() != null
                            && response.getTxInfo().getDetailList() != null
                            && response.getTxInfo().getDetailList().getDetailInfo() != null) {

                            WyzlAccountDetailResponse.DetailInfo[] details = response.getTxInfo().getDetailList().getDetailInfo();
                            if (details.length == 0) {
                                log.info("账户[{}]第{}页无数据，结束查询", bankInfo.getBankNo(), page);
                                hasMore = false;
                                break;
                            }
                            
                            log.info("账户[{}]第{}页获取到{}条明细", bankInfo.getBankNo(), page, details.length);
                            
                            for (WyzlAccountDetailResponse.DetailInfo detail : details) {
                                // 检查是否已存在该笔交易
                                if (!isTransactionExists(detail.getTranFlow())) {
                                    // 创建新的交易明细记录
                                    WsBankDetail bankDetail = new WsBankDetail();
                                    bankDetail.setBankName(bankInfo.getBankName());
                                    bankDetail.setBankNo(bankInfo.getBankNo());

                                    // 设置交易时间
                                    SimpleDateFormat txnSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                                    bankDetail.setTxnTime(txnSdf.parse(detail.getTranDate() + " " + detail.getTranTime()));

                                    // 设置交易金额
                                    BigDecimal txnAmount = new BigDecimal(detail.getAmt());
                                    bankDetail.setTxnAmount(txnAmount);

                                    // 设置交易类型和收支方向
                                    bankDetail.setTxnType(detail.getCreTyp());
                                    bankDetail.setIncOrExp("1".equals(detail.getFlag1()) ? "收入" : "支出");

                                    // 设置对方账户信息
                                    bankDetail.setTargetNo(detail.getAccNo2());
                                    bankDetail.setTargetCompanyName(detail.getAccName1());
                                    bankDetail.setTargetBankName(detail.getCadBankNm());

                                    // 设置部门信息
                                    bankDetail.setDepartId(bankInfo.getDepartId());
                                    bankDetail.setDepartName(bankInfo.getDepartName());

                                    // 设置交易流水号
                                    bankDetail.setTranFlow(detail.getTranFlow());

                                    // 保存交易明细
                                    wsBankDetailService.save(bankDetail);
                                    log.info("账户[{}]新增交易明细：{}", bankInfo.getBankNo(), detail.getTranFlow());

                                    // 检查并保存大额交易
                                    checkAndSaveBlockTrade(bankInfo, detail, txnAmount);
                                }
                            }
                            // 判断是否还有下一页
                            if (details.length < pageSize) {
                                log.info("账户[{}]第{}页数据不足{}条，结束查询", bankInfo.getBankNo(), page, pageSize);
                                hasMore = false;
                            } else {
                                page++;
                            }
                        } else {
                            log.error("账户[{}]第{}页明细查询失败，错误码：{}，错误信息：{}",
                                bankInfo.getBankNo(), page, response.getReturnCode(), response.getReturnMsg());
                            hasMore = false;
                        }
                    }
                    
                    if (page > maxPage) {
                        log.warn("账户[{}]查询达到最大页数限制{}，强制结束查询", bankInfo.getBankNo(), maxPage);
                    }
                    
                } catch (Exception e) {
                    log.error("账户[{}]明细查询异常", bankInfo.getBankNo(), e);
                }
            }
        } catch (Exception e) {
            log.error("银行账户明细查询定时任务执行异常", e);
        }
        log.info("银行账户明细查询定时任务执行完成");
    }

    /**
     * 获取账户最近一次交易时间
     */
    private Date getLastTxnTime(String bankNo) {
        LambdaQueryWrapper<WsBankDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WsBankDetail::getBankNo, bankNo)
               .orderByDesc(WsBankDetail::getTxnTime)
               .last("LIMIT 1");
        WsBankDetail lastDetail = wsBankDetailService.getOne(wrapper);
        return lastDetail != null ? lastDetail.getTxnTime() : null;
    }

    /**
     * 检查交易是否已存在
     */
    private boolean isTransactionExists(String tranFlow) {
        LambdaQueryWrapper<WsBankDetail> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(WsBankDetail::getTranFlow, tranFlow);
        return wsBankDetailService.count(wrapper) > 0;
    }
}
